package ExpressFive;

import java.util.Scanner;

public class ThisIsABanker {

    static public class Bank {
        public final int number=3;//这是三种类型的，如果需要更改四种类型，还需要更改下面部分

        int[] Available = {8, 10, 14};//可利用资源


        int[][] Max = new int[number][number];
        int[][] Allocation = new int[number][number];
        int[][] Need = new int[number][number];
        int[][] Request = new int[number][number];
        int[] Work = new int[number];

        int num = 0;//进程编号
        Scanner in = new Scanner(System.in);
        //初始化
        public void setValue(){
            setMax();
            setAllocation();
            showValue();
            BankAlgorithm();
        }
        //设置Max矩阵
        public void setMax() {
            System.out.println("Max：");
            for (int i = 0; i < number; i++) {
                System.out.println("process P" + i + "max resource：");
                for (int j = 0; j < number; j++) {
                    Max[i][j] = in.nextInt();
                }
            }
        }
        //设置已分配矩阵Allocation
        public void setAllocation() {
            System.out.println("Allocation：");
            for (int i = 0; i < number; i++) {
                System.out.println("process P" + i + "allocate resource：");
                for (int j = 0; j < number; j++) {
                    Allocation[i][j] = in.nextInt();
                }
            }
            //设置Allocation矩阵
            System.out.println("Available = Available - Allocation.");
            System.out.println("Need = Max - Allocation.");
            for (int i = 0; i < number; i++) {
                for (int j = 0; j < number; j++) {
                    Available[i] = Available[i] - Allocation[j][i];
                }
            }
            for (int i = 0; i < number; i++) {//设置Need矩阵
                for (int j = 0; j < number; j++) {
                    Need[i][j] = Max[i][j] - Allocation[i][j];
                }
            }
        }

        public void showValue(){
            System.out.println("process \t"+"Max\t"+"Allocation\t"+"Need\t"+"Available");
            for(int i=0;i<number;i++){
                System.out.print("P"+i+"  ");
                for(int j=0;j<number;j++){
                    System.out.print(Max[i][j]+"  ");
                }
                System.out.print("|  ");
                for(int j=0;j<number;j++){
                    System.out.print(Allocation[i][j]+"  ");
                }
                System.out.print("|  ");
                for(int j=0;j<number;j++){
                    System.out.print(Need[i][j]+"  ");
                }
                System.out.print("|  ");
                if(i==0){
                    for(int j=0;j<number;j++){
                        System.out.print(Available[j]+"  ");
                    }
                }
                System.out.println();
            }
        }
        //设置请求资源量Request
        public void setRequest() {
            System.out.println("process id：");
            num= in.nextInt();
            System.out.println("process for each resource ：");
            for (int j = 0; j < number; j++) {
                Request[num][j] = in.nextInt();
            }
            System.out.println("process P" + num + "Request：(" + Request[num][0] + "," + Request[num][1] + "," + Request[num][2] + ").");
            BankerAlgorithm();
        }

        public void BankerAlgorithm() {//银行家算法
            boolean T=true;
            //判断Request是否小于Need
            if (Request[num][0] <= Need[num][0] && Request[num][1] <= Need[num][1] && Request[num][2] <= Need[num][2]) {
                //判断Request是否小于Allocation
                if (Request[num][0] <= Available[0] && Request[num][1] <= Available[1] && Request[num][2] <= Available[2]) {
                    for (int i = 0; i < number; i++) {
                        Available[i] -= Request[num][i];
                        Allocation[num][i] += Request[num][i];
                        Need[num][i] -= Request[num][i];
                    }

                } else {
                    System.out.println("can't allocate，process P" + num + "need to wait.");
                    T=false;
                }
            }
            else {
                System.out.println("process P" + num + "too large (Need).");
                T=false;
            }

            if(T){
                showValue();
                //System.out.println("现在进入安全算法：");
                BankAlgorithm();
            }
        }

        public void BankAlgorithm() {
            boolean[] Finish = {false, false, false};
            int count = 0;//完成进程数
            int circle=0;//循环圈数
            int[] S=new int[number];//安全序列
            System.arraycopy(Available, 0, Work, 0, number);
            boolean flag = true;
            while (count < number) {
                if(flag){
                    System.out.println("process\t"+"Work\t"+"\tAllocation "+"\tNeed\t"+"Work+Allocation");
                    flag = false;
                }
                for (int i = 0; i < number; i++) {

                    //判断条件,如果改成4，需要修改
                    if (!Finish[i] &&Need[i][0]<=Work[0]&&Need[i][1]<=Work[1]&&Need[i][2]<=Work[2]) {
                        System.out.print("P"+i+"\t");
                        for (int k = 0; k < number; k++){
                            System.out.print(Work[k]+"\t");
                        }
                        System.out.print("|\t");
                        for (int j = 0; j<number;j++){
                            Work[j]+= Allocation[i][j];
                        }
                        Finish[i]=true;//当当前进程能满足时
                        S[count]=i;//设置当前序列排号

                        count++;//满足进程数加1
                        for(int j=0;j<number;j++){
                            System.out.print(Allocation[i][j]+"\t");
                        }
                        System.out.print("|\t");
                        for(int j=0;j<number;j++){
                            System.out.print(Need[i][j]+"\t");
                        }
                        System.out.print("|\t");
                        for(int j=0;j<number;j++){
                            System.out.print(Work[j]+"\t");
                        }
                        System.out.println();
                    }

                }
                circle++;
                //判断是否满足所有进程需要
                if(count==number){
                    System.out.print("safe：");
                    //输出安全序列
                    for (int i = 0; i<number;i++){
                        System.out.print("P"+S[i]+"\t");
                    }
                    System.out.println("can allocate！");
                    break;//跳出循环
                }
                if(count<circle){
                    System.out.println("unsafe。");
                    break;//跳出循环
                }
            }
        }

    }


    public static void main(String[] args) {
        boolean Choose = true;
        String C;
        Scanner in = new Scanner(System.in);
        Bank T = new Bank();
        System.out.println("three type resource:{8, 10, 14}");

        T.setValue();
        while (Choose) {
            T.setRequest();
            System.out.println("continue? y/n");
            C = in.nextLine();
            if (C.endsWith("n")) {
                Choose = false;
            }
        }
    }
}
